# -*- coding:utf-8 -*-
from flask import request, current_app

from info.api.ZTCCLOUD import ZTCCLOUD
from info.utils import utils
from . import task_blu
from ...models import Task, Schedule
from ...utils.resonse import info_jsonfy
from ...utils.response_code import RET


@task_blu.route("/task_info", methods=["GET"])
def base_info():
    """首页查询基本信息和进度表中的信息"""
    # 查询所有已完成的造数接口
    currentPage = request.args.get("page", 1)
    limit = request.args.get("limit", 10)
    category = request.args.get("category")
    try:
        currentPage = abs(int(currentPage))
        limit = abs(int(limit))
    except Exception as e:
        current_app.logger.error(e)
        return info_jsonfy(500, "page和limit只能是整数")
    else:
        if limit > 100:
            return info_jsonfy(500, "limit不可大于100")

    queryConditionsList = []
    if category:
        queryConditionsList.append(Task.method_category == category)
    try:
        paginate = Task.query.filter(*queryConditionsList).\
            order_by(Task.last_update_time.desc()).\
            paginate(currentPage, limit, False)
    except Exception as e:
        current_app.logger.error(e)
        return info_jsonfy(RET.DBERR, "数据库查询错误")
    currentPage = paginate.page
    totalPage = paginate.pages
    items = paginate.items
    data = [u.to_dict() for u in items]
    data = {
        "page": currentPage,
        "totalPage": totalPage,
        "list": data
    }
    return info_jsonfy(200, "success", data)


@task_blu.route("/run_task", methods=["POST"])
def run_task():
    """执行任务"""
    reqBody = request.json
    server_addr = reqBody.get("server_ip")
    if not all((server_addr, reqBody.get("user_name"), reqBody.get("user_pwd"))):
        return info_jsonfy(500, "服务器地址、用户名和密码不可以为空")
    if not utils.check_url_format(server_addr):
        return info_jsonfy(500, "服务器地址格式不正确")
    if not reqBody.get("data"):
        return info_jsonfy(500, "未勾选任何造数据方法，请勾选后再点击执行")
    current_app.logger.info(f"user_addr: {request.headers.get('X-Real-Ip')}, requestBody: {reqBody}")
    if reqBody.get("history") != "0":
        # 查询进度表中未完成的任务
        user_addr = request.headers.get("X-Real-Ip")
        server_addr = request.json.get("server_ip")
        try:
            schedule = Schedule.query.filter(Schedule.user_ip == user_addr, Schedule.server_ip == server_addr).all()
        except Exception as e:
            current_app.logger.error(e)
            return info_jsonfy(RET.DBERR, "数据库查询错误")
        if schedule:
            data = []
            for d in schedule:
                dd = {}
                try:
                    task = Task.query.filter(Task.id == d.task_id).first()
                except Exception as e:
                    current_app.logger.error(e)
                    dd["description"] = "主表中无此数据，请联系管理员"
                    dd["status"] = "1"
                else:
                    dd["description"] = task.description
                    dd["id"] = task.id
                    dd["status"] = task.status
                data.append(dd)
            return info_jsonfy(200, "success", data)

    # --------------------
    # 执行造数据任务
    server_addr = request.json.get("server_ip")
    user_addr = request.headers.get("X-Real-Ip")
    waitExecTask = request.json.get("data")
    named_pre = request.json.get("named_pre")
    user_name = request.json.get("user_name")
    password = request.json.get("user_pwd")

    # 校验参数不可为空
    msg = ", ".join(i.get("description") for i in waitExecTask if not i.get("run_num"))
    if msg:
        return info_jsonfy(500, f"{msg} 执行次数不可为空")
    # 先登录确认环境可用
    try:
        cookie = ZTCCLOUD().GET_USER_COOKIE(server_addr, user_name, password)
    except Exception as e:
        current_app.logger.error(f"登录失败，serverAddr:{server_addr},userName:{user_name},password:{password}\n{e}")
        return info_jsonfy(500, msg="登录失败，请确认环境可用")
    else:
        if cookie == "=" or isinstance(cookie, bool):
            return info_jsonfy(500, msg="登录失败，未获取到cookie信息，请确认环境及账户信息正确")
    # 删除历史进度表中原有的数据
    try:
        Schedule.query.filter(Schedule.user_ip == user_addr, Schedule.server_ip == server_addr).delete()
    except Exception as e:
        current_app.logger.error(e)
    run_data_job(cookie, server_addr, user_addr, named_pre, waitExecTask)
    return info_jsonfy(200, "success")


@task_blu.route("/run_record", methods=["POST"])
def run_record():
    """获取执行记录"""
    reqBody = request.json
    user_addr = request.headers.get("X-Real-Ip")
    # current_app.logger.info(f"request_headers: {request.headers}")
    current_app.logger.info(f"user_addr: {user_addr}, requestBody: {reqBody}")
    server_addr = reqBody.get("server_ip")
    flag = True
    try:
        data1 = utils.cache().get(user_addr).get(server_addr)
    except AttributeError as e:
        current_app.logger.error(e)
        current_app.logger.info(f"当前整体执行结果如下：\n{utils.cache()}")
        flag = False
    else:
        if not data1:
            flag = False
    if not flag:
        return info_jsonfy(200, "暂无记录")
    # 查库获取造数方法id和描述信息
    try:
        querySet = Task.query.filter(Task.method_name.in_(f"Basic.{i}" for i in data1.keys())).all()
    except Exception as e:
        current_app.logger.error("数据库查询失败...")
        return info_jsonfy(500, "数据库查询失败，请联系管理员")
    else:
        data = []
        for i in querySet:
            d = {}
            d.update(i.to_dict())
            method_name = i.method_name.split(".")[-1]
            d["finish_num"] = data1[method_name]
            data.append(d)

    for key in ["结算科目配置", "税务科目配置", "业务科目配置", "银行/票据科目配置"]:
        finishNum = data1.get(key)
        if finishNum:
            data.append({"description": key, "finish_num": finishNum})

    return info_jsonfy(200, "success", data)


@task_blu.route("/clear_record", methods=["DELETE"])
def clear_record():
    """清除执行记录"""
    reqBody = request.json
    user_addr = request.headers.get("X-Real-Ip")
    current_app.logger.info(f"user_addr: {user_addr}, requestBody: {reqBody}")
    server_addr = reqBody.get("server_ip")
    current_app.logger.info(utils.cache())
    utils.clear_cache(user_addr, server_addr)
    return info_jsonfy(200, "success")


def run_data_job(cookie, server_addr, user_addr, named_pre, waitExecTask):
    """具体执行任务的方法"""
    from manager import app

    def get_result(future):
        with app.app_context():
            current_app.logger.info(future.result())

    waitExecTaskIds = [i.get("id") for i in waitExecTask]
    waitExecTaskNumGlobal = [i.get("run_num") for i in waitExecTask]
    try:
        waitExecT1 = Task.query.filter(Task.id.in_(waitExecTaskIds)).all()
    except Exception as e:
        current_app.logger.error(e)
        return info_jsonfy(500, "数据库查询异常，请联系管理员")
    waitExecT = []
    for i in waitExecTaskIds:
        for j in waitExecT1:
            if j.id == i:
                waitExecT.append(j)
                break

    for i, j in zip(waitExecT, waitExecTaskNumGlobal):
        # 执行造数据方法
        cls, method = i.method_name.split(".")
        exec(f"from {i.method_path} import {cls}")
        current_app.logger.info(f"开始准备【{i.description}】数据，待执行次数：{j}")
        method = eval(f"{cls}().{method}")
        future = app.ThreadPoolExecutor.submit(method, **{
            "server_addr": server_addr, "user_addr": user_addr,
            "run_num": j, "named_pre": named_pre, "task_id": i.id,
            "cookie": cookie
        })
        future.add_done_callback(get_result)
